winbrew_app\operations\update/
api.rs1use anyhow::{Context, Result};
2use url::Url;
3
4use crate::core::network::Client;
5use crate::models::catalog::CatalogMetadata;
6
7use super::types::CatalogUpdateResponse;
8
9pub(super) fn fetch_catalog_update_selection(
19 client: &Client,
20 update_api_url: &str,
21 local_metadata: Option<&CatalogMetadata>,
22) -> Result<CatalogUpdateResponse> {
23 fetch_catalog_update_selection_with_current_hash(
24 client,
25 update_api_url,
26 local_metadata.map(|metadata| metadata.current_hash.as_str()),
27 )
28}
29
30pub(super) fn fetch_full_snapshot_update_selection(
39 client: &Client,
40 update_api_url: &str,
41) -> Result<CatalogUpdateResponse> {
42 fetch_catalog_update_selection_with_current_hash(client, update_api_url, None)
43}
44
45fn fetch_catalog_update_selection_with_current_hash(
46 client: &Client,
47 update_api_url: &str,
48 current_hash: Option<&str>,
49) -> Result<CatalogUpdateResponse> {
50 let api_url = build_update_api_url(update_api_url, current_hash).with_context(|| {
51 format!("failed to build catalog update selection URL from {update_api_url}")
52 })?;
53
54 let response = client
55 .get(api_url.as_str())
56 .send()
57 .with_context(|| format!("failed to send catalog update selection request to {api_url}"))?
58 .error_for_status()
59 .with_context(|| format!("catalog update selection request failed for {api_url}"))?;
60
61 response.json().with_context(|| {
62 format!("failed to decode catalog update selection response from {api_url}")
63 })
64}
65
66fn build_update_api_url(update_api_url: &str, current_hash: Option<&str>) -> Result<Url> {
67 let mut url = Url::parse(update_api_url).context("invalid catalog update selection API URL")?;
68
69 if let Some(current_hash) = current_hash {
70 url.query_pairs_mut().append_pair("current", current_hash);
71 }
72
73 Ok(url)
74}
75
76#[cfg(test)]
77mod tests {
78 use super::build_update_api_url;
79
80 #[test]
81 fn build_update_api_url_appends_current_hash() {
82 let url = build_update_api_url("https://example.invalid/v1/update", Some("sha256:abc123"))
83 .expect("build url");
84
85 assert_eq!(
86 url.as_str(),
87 "https://example.invalid/v1/update?current=sha256%3Aabc123"
88 );
89 }
90
91 #[test]
92 fn build_update_api_url_preserves_existing_query_parameters() {
93 let url = build_update_api_url(
94 "https://example.invalid/v1/update?feature=preview",
95 Some("sha256:abc123"),
96 )
97 .expect("build url");
98
99 assert_eq!(
100 url.as_str(),
101 "https://example.invalid/v1/update?feature=preview¤t=sha256%3Aabc123"
102 );
103 }
104}